package service

import (
	"fmt"
	lru "github.com/hashicorp/golang-lru/v2"
	cron "github.com/robfig/cron/v3"
	"lktx-dns/bean"
	"lktx-dns/db"
	"lktx-dns/entity"
	"log"
	"sync"
	"time"
)

type CacheService struct {
	//网站/访问次数
	PVMu sync.RWMutex
	PV   *lru.Cache[string, int64]
	//网站/访问人数
	UVMu sync.RWMutex
	UV   *lru.Cache[string, *bean.Set]
	//IP/访问量
	IPMu sync.RWMutex
	IP   *lru.Cache[string, int64]
	//网站/上传
	UploadMu sync.RWMutex
	Upload   *lru.Cache[string, int64]
	//网站/下载
	DownloadMu sync.RWMutex
	Download   *lru.Cache[string, int64]
	//域名/成功次数
	DNSSuccessMu sync.RWMutex
	DNSSuccess   *lru.Cache[string, int64]
	//域名/失败次数
	DNSErrorMu sync.RWMutex
	DNSError   *lru.Cache[string, int64]
}

func (receiver CacheService) statCache() {
	var c = cron.New()
	c.AddFunc("@daily", func() {
		receiver.saveData()
	})
	//c.AddFunc("@every 10s", func() {
	//	receiver.saveData()
	//})
	c.Start()
	select {}
}

func (receiver CacheService) saveData() {
	defer func() {
		if r := recover(); r != nil {
			log.Println("保存异常:", r)
		}
	}()
	for i := 0; i < 7; i++ {
		data := receiver.GetData(i)
		if data != nil && len(data) > 0 {
			var slice []entity.StatEntity
			for s, i2 := range data {
				statEntity := entity.StatEntity{
					Type:  i,
					Key:   s,
					Value: i2,
				}
				slice = append(slice, statEntity)
			}
			db.DB.Create(&slice)
		}
		receiver.ClearData(i)
	}
	//清除时间超过7天的数据
	receiver.delOldData()
	log.Println("数据缓存保存")
}

func (receiver CacheService) delOldData() {
	// 获取当前时间和7天前的时间
	now := time.Now()
	sevenDaysAgo := now.AddDate(0, 0, -7)
	sevenDaysAgoDate := sevenDaysAgo.Format("2006-01-02")
	db.DB.Where("DATE(created) < ?", sevenDaysAgoDate).Delete(&entity.StatEntity{})
}

func NewCacheService() *CacheService {
	receiver := &CacheService{}
	a, err := lru.New[string, int64](100000)
	if err == nil {
		receiver.PV = a
	}
	b, err := lru.New[string, *bean.Set](100000)
	if err == nil {
		receiver.UV = b
	}
	c, err := lru.New[string, int64](100000)
	if err == nil {
		receiver.IP = c
	}
	d, err := lru.New[string, int64](100000)
	if err == nil {
		receiver.Upload = d
	}
	e, err := lru.New[string, int64](100000)
	if err == nil {
		receiver.Download = e
	}
	f, err := lru.New[string, int64](100000)
	if err == nil {
		receiver.DNSSuccess = f
	}
	g, err := lru.New[string, int64](100000)
	if err == nil {
		receiver.DNSError = g
	}
	go receiver.statCache()
	return receiver
}

func (receiver CacheService) AddPv(host string) {
	defer receiver.PVMu.Unlock()
	receiver.PVMu.Lock()
	value, ok := receiver.PV.Get(host)
	if ok {
		receiver.PV.Add(host, value+1)
	} else {
		receiver.PV.Add(host, 1)
	}
}
func (receiver CacheService) AddUv(host string, ip string) {
	defer receiver.UVMu.Unlock()
	receiver.UVMu.Lock()
	value, ok := receiver.UV.Get(host)
	if ok {
		value.Add(ip)
	} else {
		set := bean.NewSet()
		set.Add(ip)
		receiver.UV.Add(host, set)
	}
}

func (receiver CacheService) AddIp(host string) {
	defer receiver.IPMu.Unlock()
	receiver.IPMu.Lock()
	value, ok := receiver.IP.Get(host)
	if ok {
		receiver.IP.Add(host, value+1)
	} else {
		receiver.IP.Add(host, 1)
	}
}

func (receiver CacheService) AddUpload(host string, size int64) {
	defer receiver.UploadMu.Unlock()
	receiver.UploadMu.Lock()
	value, ok := receiver.Upload.Get(host)
	if ok {
		receiver.Upload.Add(host, value+size)
	} else {
		receiver.Upload.Add(host, size)
	}
}

func (receiver CacheService) AddDownload(host string, size int64) {
	defer receiver.DownloadMu.Unlock()
	receiver.DownloadMu.Lock()
	value, ok := receiver.Download.Get(host)
	if ok {
		receiver.Download.Add(host, value+size)
	} else {
		receiver.Download.Add(host, size)
	}

}

func (receiver CacheService) AddDNSSuccess(host string) {
	defer receiver.DNSSuccessMu.Unlock()
	receiver.DNSSuccessMu.Lock()
	value, ok := receiver.DNSSuccess.Get(host)
	if ok {
		receiver.DNSSuccess.Add(host, value+1)
	} else {
		receiver.DNSSuccess.Add(host, 1)
	}
}

func (receiver CacheService) AddDNSError(host string) {
	defer receiver.DNSErrorMu.Unlock()
	receiver.DNSErrorMu.Lock()
	value, ok := receiver.DNSError.Get(host)
	if ok {
		receiver.DNSError.Add(host, value+1)
	} else {
		receiver.DNSError.Add(host, 1)
	}
}

func (receiver CacheService) GetGroupType() interface{} {
	var result []struct {
		Date string `json:"date"`
	}
	// 按年月日分组统计每一天的 Value 总和
	err := db.DB.Model(&entity.StatEntity{}).Select(" DATE(created) as date").Group("date").Scan(&result).Error
	if err != nil {
		fmt.Println("Error querying database:", err)
		return nil
	}
	return result

}

func (receiver CacheService) GetTimeType(time string, t int) []entity.StatEntity {
	var result []entity.StatEntity
	err := db.DB.Where("DATE(created) = ? and type=?", time, t).Find(&result).Error
	if err != nil {
		return nil
	}
	return result
}

func (receiver CacheService) GetData(t int) map[string]int64 {
	switch t {
	case 0:
		{
			pv := map[string]int64{}
			keys := receiver.PV.Keys()
			for _, key := range keys {
				value, ok := receiver.PV.Get(key)
				if ok {
					pv[key] = value
				}
			}
			return pv
		}
	case 1:
		{
			uv := map[string]int64{}
			keys := receiver.UV.Keys()
			for _, key := range keys {
				value, ok := receiver.UV.Get(key)
				if ok {
					uv[key] = int64(value.Size())
				}
			}
			return uv

		}
	case 2:
		{
			ip := map[string]int64{}
			keys := receiver.IP.Keys()
			for _, key := range keys {
				value, ok := receiver.IP.Get(key)
				if ok {
					ip[key] = value
				}
			}
			return ip
		}
	case 3:
		{
			upload := map[string]int64{}
			keys := receiver.Upload.Keys()
			for _, key := range keys {
				value, ok := receiver.Upload.Get(key)
				if ok {
					upload[key] = value
				}
			}
			return upload

		}
	case 4:
		{
			download := map[string]int64{}
			keys := receiver.Download.Keys()
			for _, key := range keys {
				value, ok := receiver.Download.Get(key)
				if ok {
					download[key] = value
				}
			}
			return download
		}
	case 5:
		{
			dnsSuccess := map[string]int64{}
			keys := receiver.DNSSuccess.Keys()
			for _, key := range keys {
				value, ok := receiver.DNSSuccess.Get(key)
				if ok {
					dnsSuccess[key] = value
				}
			}
			return dnsSuccess
		}
	case 6:
		{
			dnsError := map[string]int64{}
			keys := receiver.DNSError.Keys()
			for _, key := range keys {
				value, ok := receiver.DNSError.Get(key)
				if ok {
					dnsError[key] = value
				}
			}
			return dnsError
		}
	}
	return nil
}

func (receiver CacheService) ClearData(t int) {

	switch t {
	case 0:
		{
			receiver.PV.Purge()
		}
	case 1:
		{
			keys := receiver.UV.Keys()
			for _, key := range keys {
				value, ok := receiver.UV.Get(key)
				if ok {
					value.Clear()
				}
			}
			receiver.UV.Purge()
		}
	case 2:
		{
			receiver.IP.Purge()
		}
	case 3:
		{
			receiver.Upload.Purge()
		}
	case 4:
		{
			receiver.Download.Purge()
		}
	case 5:
		{
			receiver.DNSSuccess.Purge()
		}
	case 6:
		{
			receiver.DNSError.Purge()
		}
	}
}
